﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;

namespace Game.Global.Helper
{
    /// <summary>
    /// 字符串相关的Helper
    /// <para>包括String的本地化</para>
    /// </summary>
	public static class StringHelper 
	{
		//---------------------------------------------------------------------------
		//				Public area
		//---------------------------------------------------------------------------
		#region Public area

        /// <summary>
        /// 将字符串转换为对应的枚举类型(忽略大小写)
        /// </summary>
        /// <remarks>不要使用扩展方法，以避免对string方法污染</remarks>
        public static T StrToEnum<T>(string strVal)
        {
            T result = (T)System.Enum.Parse(typeof(T), strVal, true);
            return result;
        }


        /// <summary>
        /// 截取最多n个长度的单词数（单词超长则提前截断，保留到下一个），用于类似自动换行的场景；
        /// <para>ps：一行长度为n，当前语句长度超过n时，将不保留导致超过的单词，只截取前面一段。</para>
        /// </summary>
        /// <param name="preferLength">优先取单词的总长度，如果单词超过，则提前截取单词</param>
        /// <param name="actualLength">实际上剪切下来的单词的长度</param>
        /// <remarks> sample 示例代码:
        /// string input = Console.ReadLine();
        /// int actual, wordsGot =  0;
        /// while (wordsGot 《 input.Length)
        /// {
        ///        Console.WriteLine("RESULT:" + GetWords(input, wordsGot, 20, out actual)); //将返回不超过20个长度的n个单词
        ///        wordsGot += actual;
        /// }
        /// </remarks>
        public static string GetWords(string src, int startFrom, int preferLength, out int actualLength)
        {
            //--最近遇到的空格
            int latestSpaceIndex = startFrom;

            //--检查：如果单词本来就不超出范围，则提前退出
            if (preferLength + startFrom > src.Length)
            {
                actualLength = src.Length - startFrom;
                return src.Substring(startFrom);
            }

            int endIndex = preferLength + startFrom;

            //--找到最靠近预定长度的空格：
            for (int i = startFrom; i < endIndex; i++)
            {
                if (src[i] == ' ')
                {
                    latestSpaceIndex = i;
                }
            }

            //--异常情况（从一开始至今就没有遇到过空格，也就是字符超长导致无法分割，则应该找到这个超长单词结束的地方，或者语句结束）
            if (latestSpaceIndex == startFrom)
            {
                //--从上一轮结束的地方开始：
                int i = endIndex;
                int srcLength = src.Length;
                //--继续循环直到字符串结束：
                while (true)
                {
                    if (i >= srcLength)
                    {
                        //--end of string
                        latestSpaceIndex = srcLength - 1;
                        break;
                    }
                    else if (src[i] == ' ')
                    {
                        //Got SPACE finally 
                        latestSpaceIndex = i;
                        break;
                    }

                    //go on:
                    i++;

                }
            }

            //--以最后找到的的空格为准：
            actualLength = latestSpaceIndex - startFrom + 1;


            return src.Substring(startFrom, actualLength);
        }

        /// <summary>
        /// 模糊判断内容是否是大多都是英文
        /// <para>
        /// PS：这个判断方法不能完全相信，取的中间值越多越可信；如果碰巧遇到很多空格，大多会判英文，但是这是可接受的。
        /// </para>
        /// </summary>
        /// <remarks>取中间几个位置，而不会全部遍历</remarks>
        public static bool IsEnglish(string str)
        { 
            //--取长度
            int strLength = str.Length;

            //--取0,1/5,2/5,3/5,4/5的位置，如果超过一半不是英文，则不是英文
            int testCount = 5;
            int testPos;
            int nonEnglish = 0;
            for (int i = 0; i < testCount; i++)
            {
                testPos = strLength * i / testCount;
                if ((int)str[testPos] > 128)
                {
                    nonEnglish++;
                }
            }

            if (nonEnglish > testCount / 2)
            {
                return false;
            }
            else
            {
                return true;
            }
            
        }

        /// <summary>
        /// 获得某个字母的出现次数
        /// </summary>
        /// <param name="str"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        public static int GetCharCount(string str,char target)
        {
            int length = str.Length;
            int count = 0;              

            for (int i = 0; i < length; i++)
            {
                if (str[i] == target)
                {
                    count++;
                }
            }
            return count;
        }

        /// <summary>
        /// 获得字符串中的行数
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static int GetLinesCount(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return 0;
            }
            else
            {
                //返回值+1，因为只有一行的时候，后面换行符还没有出现
                return GetCharCount(str, '\n') + 1;
            }
        }

#if UNITY_EDITOR
        /// <summary>
        /// 仅在编辑器模式下运行：测试输出本地化的string的文件：顺带给出各语言的文件名
        /// </summary>
        public static void TestWriteLocalizeString()
        {
            Dictionary<string, string> localTest = new Dictionary<string, string>();
            localTest["Example"]= "示例。具体语言文件名可见下。";

            for(int i = 0;i< (int) SystemLanguage.Unknown;i++)
            {
                localTest[((SystemLanguage)i).ToString()] = "Test";
            }

            //Output
            FileHelper.Editor_SaveResource(C_LocalizationPath, SystemLanguage.English.ToString() , localTest, true);
            Debug.Log("Succ to write example localization file");
        }
#endif

        /// <summary>
        /// 翻译所有的string到本地语言
        /// <para>对于待翻译内容，必须在Resources文件夹下有对应的本地化内容文件</para>
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string LocalizeStr(string str)
        {
            var localDict = GetLocalizationDictionary();

            if(localDict==null || !localDict.ContainsKey(str))
            {
                //TODO: 在编辑器模式时，可选择将未找到的key扔到文件中，（key加个todo前缀，等确认。避免不必要的添加太多且无法删除）
                Debug.LogWarning("无法本地化的内容，请确保用于本地化的文件存在。待翻译key：[" + str+"]");

#if UNITY_EDITOR
                Debug.LogWarning("将添加该字符串内容，请及时修改其对应翻译文本");
                //编辑器模式下，添加待翻译内容的key、value
                SystemLanguage targetSysLanguage = Application.systemLanguage;
                dict_localization = FileHelper.LoadResource<Dictionary<string, string>>(C_LocalizationPath, targetSysLanguage.ToString());
                dict_localization.Add(str, str);
                //保存修改后的字典
                FileHelper.Editor_SaveResource(C_LocalizationPath, targetSysLanguage.ToString(), dict_localization, true);
#endif

                return str;
            }
            else
            {
                return localDict[str];
            }
        }


        /// <summary>
        /// 翻译所有的Text组件到本地语言
        /// </summary>
        public static void LocalizeText(UnityEngine.UI.Text textObj)
        {
            textObj.text = LocalizeStr(textObj.text);
        }

        /// <summary>
        /// 翻译所有的Text组件到本地语言
        /// </summary>
        /// <param name="nameEndsWith">text的名称如果以此结尾，则将其内容本地化</param>
        /// <param name="transTextParent"></param>
        public static void LocalizeAllText(RectTransform transTextParent, string nameEndsWith = "_localizable")
        {
            var textChildren = transTextParent.GetComponentsInChildren<UnityEngine.UI.Text>(transTextParent);
            foreach(var text in textChildren)
            {
                //名称如果以此结尾，则将其内容本地化
                if (text.name.EndsWith(nameEndsWith))
                {
                    text.text = LocalizeStr(text.text);
                }
            }
        }

        /// <summary>
        /// 获得本地化语言的字典，key为对应id，value为对应本地化内容字符串
        /// </summary>
        public static Dictionary<string, string> GetLocalizationDictionary()
        {
            if (dict_localization != null)
            {
                return dict_localization;
            }

            SystemLanguage targetSysLanguage = Application.systemLanguage;
            if(targetSysLanguage== SystemLanguage.ChineseSimplified || targetSysLanguage== SystemLanguage.ChineseTraditional)
            {
                targetSysLanguage = SystemLanguage.Chinese;
            }

            //读入文件
            dict_localization = FileHelper.LoadResource<Dictionary<string, string>>(C_LocalizationPath , targetSysLanguage.ToString());

            if(GameObjFunc.IsNullOrEmpty(dict_localization))
            {
                //找不到时直接使用一个空的dictionary
                dict_localization = new Dictionary<string, string>();

#if UNITY_EDITOR
                if(GameObjFunc.IsNullOrEmpty(dict_localization))
                {
                    TestWriteLocalizeString();
                    throw new Exception("至少得有英文的本地化文件，才能确保在找不到其他语言的情况下能够fallback到英文上。目前英文的范例文件已经建立，请前往编辑。");   
                }
#endif
            }

            return dict_localization;
        }


        #endregion

        //---------------------------------------------------------------------------
        //				Private area
        //---------------------------------------------------------------------------
        #region Private area

        #region Localization
        const string C_LocalizationPath = "Localization";
        private static Dictionary<string, string> dict_localization = null;

        #endregion Localization

        #endregion
    }
}